package com.cityu.bac.rfidDriver;

import java.lang.reflect.Method;
import java.util.UUID;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;

class BluetoothSerialPort extends SerialPort {
    
	BroadcastReceiver finishReceiver = null;
	BroadcastReceiver cwjReceiver = null;
	BluetoothDevice device = null;
    private BluetoothSocket mSocket = null;
    BluetoothAdapter adapter = null;
//    private static final UUID RFCOMM_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    private boolean found = false;

    BluetoothSerialPort(String macAdress) throws Exception{
    	device = null;
    	adapter = BluetoothAdapter.getDefaultAdapter();

    	if(!adapter.isEnabled()){
    		adapter.enable();
    		throw new Exception("bluetooth is off");
    	}

    	if(macAdress.equals(""))
        	findDevice();
    	else{
          device = adapter.getRemoteDevice(macAdress);
    	}
    	

        	if(device == null){
        		close();
        		throw new Exception("bluetooth device is null");
        	}
        	
        	
        	Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
        	mSocket = (BluetoothSocket) m.invoke(device, 1);
        	
        	
        	if(mSocket == null){
        		close();
        		throw new Exception("bluetooth socket is null");
        	}
        	try{
        		mSocket.connect();
        		mInputStream = mSocket.getInputStream();
                mOutputStream = mSocket.getOutputStream();
        	}catch(Exception e){
        		close();
        		if(e.getMessage().contains("Operation Canceled"))
        			BluetoothAdapter.getDefaultAdapter().disable();
        		throw e;
        	}
            
//        } catch (Exception e) {
//            e.printStackTrace();
//        } 
    }
    
    void findDevice() throws Exception{
    	
    	final Object lock = new Object();
    	
    	cwjReceiver = new BroadcastReceiver() {
			@Override
			public void onReceive(Context context, Intent intent) {
				// TODO Auto-generated method stub
				String action = intent.getAction();
    			if (BluetoothDevice.ACTION_FOUND.equals(action)) {
    				BluetoothDevice newDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
    				if(		newDevice.getAddress().startsWith("00:11:08:04") 
    						|| newDevice.getAddress().startsWith("00:02:5B:B3")
    						|| newDevice.getAddress().startsWith("00:02:0A:01")){
    					if(!found){
    						found = true;
	    					device = newDevice;
		    				adapter.cancelDiscovery();
	    					synchronized(lock){
		    					lock.notifyAll();
		    				}
    					}
    				}
    			}
			}
    	};
    	
    	finishReceiver = new BroadcastReceiver() {
			@Override
			public void onReceive(Context context, Intent intent) {
				// TODO Auto-generated method stub
				String action = intent.getAction();
    			if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
    				adapter.cancelDiscovery();
					synchronized(lock){
    					lock.notifyAll();
    				}
    				
    			}
			}
    	};
    	
    	IntentFilter cwjFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
    	IntentFilter finishFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
    	try{
    		RfidDriver.context.registerReceiver(finishReceiver, finishFilter);
    		RfidDriver.context.registerReceiver(cwjReceiver,cwjFilter);
    	}catch(Exception e){

    	}
    	adapter.startDiscovery();
    	
    	synchronized(lock){
			try {
				lock.wait(15000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
    }

    @Override
    void close() {
    	adapter.cancelDiscovery();
        try {
        	if(mSocket != null)
        		mSocket.close();
        	if(cwjReceiver != null){
	            RfidDriver.context.unregisterReceiver(cwjReceiver);
				RfidDriver.context.unregisterReceiver(finishReceiver);
        	}
        } catch (Exception e) {
//            e.printStackTrace();
        }
    }
    
    public String getName(){
		return device.getAddress();
	}

}
